#!/bin/bash
# CH9344串口驱动一键配置脚本
# 适用于: Ubuntu/Debian/其他Linux系统
# 功能: 编译、安装驱动,配置开机自动加载和权限
# 使用方法: sudo bash 配置串口驱动.sh

set -e

echo "============================================"
echo "  CH9344 串口驱动自动配置脚本"
echo "  版本: 1.0"
echo "  作者: OrangePI Gateway Team"
echo "============================================"
echo ""

# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 检查是否以root权限运行
if [ "$EUID" -ne 0 ]; then
    echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
    echo "用法: sudo bash 配置串口驱动.sh"
    exit 1
fi

# 获取实际用户(非root)
ACTUAL_USER=${SUDO_USER:-$USER}
if [ "$ACTUAL_USER" = "root" ]; then
    echo -e "${YELLOW}警告: 检测到root用户,请确认要为哪个用户配置权限${NC}"
    read -p "请输入用户名 (默认: root): " INPUT_USER
    ACTUAL_USER=${INPUT_USER:-root}
fi

echo -e "${BLUE}配置信息:${NC}"
echo "  操作系统: $(lsb_release -d 2>/dev/null | cut -f2 || uname -s)"
echo "  内核版本: $(uname -r)"
echo "  目标用户: $ACTUAL_USER"
echo "  当前目录: $(pwd)"
echo ""

# 步骤1: 检查并安装依赖
echo -e "${BLUE}[1/8]${NC} 检查编译依赖..."
MISSING_DEPS=0

if ! command -v gcc &> /dev/null; then
    echo -e "  ${YELLOW}⚠${NC} 缺少 gcc"
    MISSING_DEPS=1
fi

if ! command -v make &> /dev/null; then
    echo -e "  ${YELLOW}⚠${NC} 缺少 make"
    MISSING_DEPS=1
fi

if [ ! -d "/usr/src/linux-headers-$(uname -r)" ] && [ ! -d "/lib/modules/$(uname -r)/build" ]; then
    echo -e "  ${YELLOW}⚠${NC} 缺少 kernel headers"
    MISSING_DEPS=1
fi

if [ $MISSING_DEPS -eq 1 ]; then
    echo -e "${YELLOW}正在安装依赖...${NC}"
    if command -v apt-get &> /dev/null; then
        apt-get update
        apt-get install -y build-essential linux-headers-$(uname -r)
    elif command -v yum &> /dev/null; then
        yum install -y gcc make kernel-devel-$(uname -r)
    else
        echo -e "${RED}错误: 不支持的包管理器,请手动安装: gcc, make, kernel-headers${NC}"
        exit 1
    fi
fi
echo -e "${GREEN}✓${NC} 编译依赖已满足"
echo ""

# 步骤2: 检查驱动源码
echo -e "${BLUE}[2/8]${NC} 检查驱动源码..."
DRIVER_DIR=""

# 优先查找已解压的目录
if [ -d "LINUX/driver" ]; then
    DRIVER_DIR="LINUX/driver"
    echo -e "${GREEN}✓${NC} 找到驱动目录: $DRIVER_DIR"
elif [ -f "CH9344SER_LINUX.ZIP" ]; then
    echo -e "  ${YELLOW}⚠${NC} 需要解压 CH9344SER_LINUX.ZIP"
    if command -v unzip &> /dev/null; then
        unzip -q CH9344SER_LINUX.ZIP
        DRIVER_DIR="LINUX/driver"
        echo -e "${GREEN}✓${NC} 解压完成: $DRIVER_DIR"
    else
        echo -e "${RED}错误: 未找到 unzip 命令${NC}"
        apt-get install -y unzip || yum install -y unzip
        unzip -q CH9344SER_LINUX.ZIP
        DRIVER_DIR="LINUX/driver"
    fi
else
    echo -e "${RED}错误: 未找到驱动文件${NC}"
    echo "请确保以下文件之一存在:"
    echo "  1. LINUX/driver/ 目录"
    echo "  2. CH9344SER_LINUX.ZIP 文件"
    exit 1
fi
echo ""

# 步骤3: 编译驱动
echo -e "${BLUE}[3/8]${NC} 编译驱动模块..."
cd "$DRIVER_DIR"
make clean &>/dev/null || true
if make; then
    echo -e "${GREEN}✓${NC} 驱动编译成功"
else
    echo -e "${RED}✗${NC} 驱动编译失败"
    exit 1
fi

if [ ! -f "ch9344.ko" ]; then
    echo -e "${RED}错误: 未生成 ch9344.ko 文件${NC}"
    exit 1
fi

MODULE_SIZE=$(stat -c%s ch9344.ko)
echo -e "  模块大小: ${MODULE_SIZE} 字节"
cd - > /dev/null
echo ""

# 步骤4: 安装驱动到系统
echo -e "${BLUE}[4/8]${NC} 安装驱动到系统..."
KERNEL_VERSION=$(uname -r)
TARGET_DIR="/lib/modules/$KERNEL_VERSION/kernel/drivers/usb/serial"

mkdir -p "$TARGET_DIR"
cp "$DRIVER_DIR/ch9344.ko" "$TARGET_DIR/"
chmod 644 "$TARGET_DIR/ch9344.ko"

echo -e "${GREEN}✓${NC} 驱动已复制到: $TARGET_DIR/ch9344.ko"

# 更新模块依赖
depmod -a
echo -e "${GREEN}✓${NC} 模块依赖已更新"
echo ""

# 步骤5: 配置开机自动加载
echo -e "${BLUE}[5/8]${NC} 配置开机自动加载..."
if ! grep -q "^ch9344" /etc/modules 2>/dev/null; then
    echo "ch9344" >> /etc/modules
    echo -e "${GREEN}✓${NC} 已添加到 /etc/modules"
else
    echo -e "${GREEN}✓${NC} 已存在于 /etc/modules"
fi
echo ""

# 步骤6: 创建udev规则
echo -e "${BLUE}[6/8]${NC} 配置udev规则..."
UDEV_RULES="/etc/udev/rules.d/99-ch9344.rules"

cat > "$UDEV_RULES" <<'EOF'
# udev rules for CH9344 USB to serial converter
# 自动设置CH9344设备权限

# CH9344 USB to Serial - 支持多种产品ID
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d9", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="e018", MODE="0666", GROUP="dialout"

# 按驱动名称匹配
SUBSYSTEM=="tty", DRIVERS=="ch9344", MODE="0666", GROUP="dialout"

# 创建符号链接(可选)
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d9", SYMLINK+="ch9344_%n"
EOF

chmod 644 "$UDEV_RULES"
echo -e "${GREEN}✓${NC} udev规则已创建: $UDEV_RULES"

# 重新加载udev规则
udevadm control --reload-rules
udevadm trigger --subsystem-match=tty
echo -e "${GREEN}✓${NC} udev规则已重新加载"
echo ""

# 步骤7: 配置用户权限
echo -e "${BLUE}[7/8]${NC} 配置用户权限..."
if groups "$ACTUAL_USER" | grep -q dialout; then
    echo -e "${GREEN}✓${NC} 用户 $ACTUAL_USER 已在 dialout 组中"
else
    usermod -a -G dialout "$ACTUAL_USER"
    echo -e "${GREEN}✓${NC} 已将用户 $ACTUAL_USER 添加到 dialout 组"
    echo -e "${YELLOW}注意: 需要重新登录才能生效${NC}"
fi
echo ""

# 步骤8: 加载驱动
echo -e "${BLUE}[8/8]${NC} 加载驱动模块..."

# 卸载已存在的模块
if lsmod | grep -q ch9344; then
    echo -e "  ${YELLOW}⚠${NC} 检测到已加载的ch9344模块,正在重新加载..."
    rmmod ch9344 2>/dev/null || true
fi

# 加载新模块
if modprobe ch9344; then
    echo -e "${GREEN}✓${NC} ch9344 驱动已加载"
else
    echo -e "${RED}✗${NC} 驱动加载失败"
    exit 1
fi

# 验证驱动加载
if lsmod | grep -q ch9344; then
    echo -e "${GREEN}✓${NC} 驱动运行正常"
    lsmod | grep ch9344
else
    echo -e "${RED}✗${NC} 驱动未正确加载"
    exit 1
fi
echo ""

# 最终验证
echo "============================================"
echo -e "${GREEN}✅ 配置完成!${NC}"
echo "============================================"
echo ""

# 检查USB设备
echo -e "${BLUE}设备检测:${NC}"
if lsusb | grep -q "1a86"; then
    echo -e "${GREEN}✓${NC} 找到WCH USB设备:"
    lsusb | grep "1a86"
else
    echo -e "${YELLOW}⚠${NC} 未检测到WCH USB设备"
    echo "  请检查USB转串口设备是否已连接"
fi
echo ""

# 检查串口设备
if ls /dev/ttyCH9344USB* >/dev/null 2>&1; then
    echo -e "${GREEN}✓${NC} 串口设备已创建 (共$(ls /dev/ttyCH9344USB* | wc -l)个):"
    ls -l /dev/ttyCH9344USB* | awk '{printf "  %-25s %s:%s  权限:%s\n", $NF, $3, $4, $1}'
else
    echo -e "${YELLOW}⚠${NC} 未找到串口设备"
    echo "  可能原因:"
    echo "    1. USB设备未连接"
    echo "    2. 需要重新插拔USB设备"
fi
echo ""

# 显示配置摘要
echo -e "${BLUE}配置摘要:${NC}"
echo "  ✅ 驱动位置: $TARGET_DIR/ch9344.ko"
echo "  ✅ 开机加载: /etc/modules"
echo "  ✅ udev规则: $UDEV_RULES"
echo "  ✅ 用户权限: $ACTUAL_USER → dialout组"
echo "  ✅ 驱动状态: 已加载"
echo ""

# 后续步骤
echo -e "${BLUE}后续步骤:${NC}"
echo "  1. 如果USB设备已连接,重新插拔以触发udev规则"
echo "  2. 重新登录或运行: newgrp dialout (激活组权限)"
echo "  3. 测试串口访问: cat /dev/ttyCH9344USB0"
echo "  4. 运行应用程序"
echo ""

echo -e "${GREEN}重启后驱动会自动加载,无需手动操作!${NC}"
echo ""

# 创建验证脚本
VERIFY_SCRIPT="/home/$ACTUAL_USER/verify_ch9344.sh"
cat > "$VERIFY_SCRIPT" <<'VERIFY_EOF'
#!/bin/bash
echo "=== CH9344 驱动验证 ==="
echo ""
echo "1. 驱动状态:"
lsmod | grep ch9344 && echo "  ✓ 已加载" || echo "  ✗ 未加载"
echo ""
echo "2. USB设备:"
lsusb | grep 1a86 || echo "  未找到"
echo ""
echo "3. 串口设备:"
ls -l /dev/ttyCH9344USB* 2>/dev/null || echo "  未找到"
echo ""
echo "4. 用户组:"
groups | grep dialout && echo "  ✓ 在dialout组" || echo "  ✗ 不在dialout组"
VERIFY_EOF

chmod +x "$VERIFY_SCRIPT"
chown "$ACTUAL_USER:$ACTUAL_USER" "$VERIFY_SCRIPT"

echo -e "${GREEN}✓${NC} 已创建验证脚本: $VERIFY_SCRIPT"
echo "  运行: bash $VERIFY_SCRIPT"
echo ""

echo "============================================"
echo -e "${GREEN}🎉 安装成功!${NC}"
echo "============================================"
